package com.google.code.p.localspinner;

import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Locale;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Color;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.MenuItem.OnMenuItemClickListener;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import com.google.code.p.localspinner.SearchHelper.SearchType;
import com.google.code.p.localspinner.database.UserdataAdapter;

public class Search extends Activity{
    
    private static final String PLEASE_ENTER_LOCATION_FOR_EVENT_SEARCH = "Please enter location for event search";
    private static final String PLEASE_ENTER_BOTH_QUERY_AND_LOCATION_FOR_LOCAL_SEARCH = "Please enter both query AND location for local search";
    private static final String WHAT_ARE_YOU_LOOKING_FOR = "What are you looking for?";
    private static final String CANCEL = "Cancel";
    private static final String SELECT_YOUR_LOCATION = "Select Your Location";
    
    private SearchHelper searchHelper = null;
  
  private Geocoder geocoder = null;
  
  private LocationManager locationManager = null;
  private Location lastLocation = null;
  private VersionChecker versionChecker = null;
  
  private final LocationListener onLocationChange = new LocationListener() {
      public void onLocationChanged(Location location) {
          if(location != null){
              lastLocation = location;
          }
      }
      
      public void onProviderDisabled(String provider) {
          //ignore
      }
      
      public void onProviderEnabled(String provider) {
          //ignore
      }
      
      public void onStatusChanged(String provider, int status, Bundle extras) {
          // required for interface, not used
      }
  };
      
  private class MyLocationClick implements OnClickListener{
    @Override
    public void onClick(View v) {
      showMyLocationsDialog();
    }
  }
  

  private void showMyLocationsDialog(){
    
    Location myLocation = lastLocation;
          
    if(locationManager != null && myLocation == null){
        myLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
        if(myLocation == null){
            myLocation = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
        }
        if(myLocation == null){
            for(String provider : locationManager.getAllProviders()){                  
                if(!LocationManager.GPS_PROVIDER.equalsIgnoreCase(provider) && 
                        !LocationManager.NETWORK_PROVIDER.equalsIgnoreCase(provider)){
                    myLocation = locationManager.getLastKnownLocation(provider);
                }
            }
        }
    }
    
    List<Address> myLocations = null;
    try {
        myLocations = geocoder == null ? Collections.<Address>emptyList() : 
              geocoder.getFromLocation(myLocation.getLatitude(), myLocation.getLongitude(), 5);
    } catch (IOException e) {
      showMessage("Unable to determine your current location.");
        return;
    }
    if(myLocations != null && myLocations.size()> 0){
        showSelectDialog(AppUtils.addressToString(myLocations), SELECT_YOUR_LOCATION, locationTxt);
    }else{
        showMessage("Unable to determine your current location.");
    }
    
  }
  
  private void showListDialog(final Cursor cursor, final String title){
    Dialog dialog = new AlertDialog.Builder(this)
    .setIcon(R.drawable.alert_dialog_icon)
    .setTitle(title)
    .setNegativeButton(CANCEL, NO_ACTION_CLICK_LISTENER)
    .setCursor(cursor, 
        new android.content.DialogInterface.OnClickListener(){
          @Override
          public void onClick(DialogInterface dialog, int which) {
            Dialog action = new AlertDialog.Builder(Search.this)
            .setIcon(R.drawable.alert_dialog_icon)
            .setTitle("Select an action to be performed for list ["+cursor.getString(1)+"]\nPress phone's back button to cancel.")
            .setPositiveButton("Load", new android.content.DialogInterface.OnClickListener(){
              @Override
              public void onClick(DialogInterface dialog, int which) {
                searchHelper.searchFromDb(userData, cursor.getLong(0));
              }
            })
            .setNegativeButton("Delete", new android.content.DialogInterface.OnClickListener(){
              @Override
              public void onClick(DialogInterface dialog, int which) {
                if(userData.deleteList(cursor.getLong(0))){
                  showMessage("List deleted.");
                }else{
                  showMessage("Unable to delete list.");
                }
              }
            })
            .create();
            action.show();
          }
        }, UserdataAdapter.COLUMN_NAME)
    .create();
    dialog.show();
  }
  
  private void showSelectDialog(final CharSequence[] items, String title, final EditText editTxt){
   Dialog dialog = new AlertDialog.Builder(this)
   .setIcon(R.drawable.alert_dialog_icon)
   .setTitle(title)
   .setNegativeButton(CANCEL, NO_ACTION_CLICK_LISTENER)
   .setItems(items, 
       new android.content.DialogInterface.OnClickListener(){

         @Override
         public void onClick(DialogInterface dialog, int which) {
             editTxt.setText(items[which]);
         }
       })
   .create();
   dialog.show();
 }
  
  private EditText locationTxt = null;
  private static final android.content.DialogInterface.OnClickListener NO_ACTION_CLICK_LISTENER = 
      new android.content.DialogInterface.OnClickListener(){public void onClick(DialogInterface dialog, int which) {}};
  private static final int PREFERENCE_ID = Menu.FIRST;
  
  private UserdataAdapter userData;
  
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        
        menu.add(0, PREFERENCE_ID, 0, "Settings").setIcon(R.drawable.settings).setOnMenuItemClickListener(new OnMenuItemClickListener(){

            @Override
            public boolean onMenuItemClick(MenuItem item) {
                Intent launchPreferencesIntent = new Intent(Search.this, Preferences.class);
                
                // Make it a subactivity so we know when it returns
                startActivityForResult(launchPreferencesIntent, 1);
                return true;
            }
            
        });
        return true;
    }
  
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
    
    searchHelper = new SearchHelper(this);
    userData = new UserdataAdapter(this);
    userData.open();
    try {
        this.versionChecker = new VersionChecker(this);
        versionChecker.checkVersionAvailable();
    } catch (Exception e) {
        Log.e(Search.class.toString(), e.getMessage(), e); //ignore version check error
    }
    
    try {
      this.geocoder = new Geocoder(this, Locale.US);
    } catch (Exception e) {}

    this.locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);     
    
    final EditText queryTxt = (EditText) findViewById(R.id.query);
    locationTxt = (EditText) findViewById(R.id.location);
    
    View myLocation = (View)findViewById(R.id.mylocation);
    myLocation.setOnClickListener(new MyLocationClick());
    
    View queryPreset = (View)findViewById(R.id.preset);
    queryPreset.setOnClickListener(new OnClickListener(){
        @Override
        public void onClick(View v) {
            showSelectDialog(StaticMemory.QUERY_PRESET, WHAT_ARE_YOU_LOOKING_FOR, queryTxt);
        }
    });
    
    TextView title = (TextView) findViewById(R.id.search_title);
    title.setShadowLayer(0.5f, 2, 2, Color.BLACK);
    TextView title2 = (TextView) findViewById(R.id.my_list_title);
    title2.setShadowLayer(0.5f, 2, 2, Color.BLACK);
    TextView title3 = (TextView) findViewById(R.id.search_title_event);
    title3.setShadowLayer(0.5f, 2, 2, Color.BLACK);
    Button searchLocal = (Button)findViewById(R.id.search_local);
    searchLocal.setOnClickListener(new OnClickListener(){
      @Override
      public void onClick(View v) {
          if(AppUtils.isBlank(queryTxt) && AppUtils.isBlank(locationTxt)){
              showMessage(PLEASE_ENTER_BOTH_QUERY_AND_LOCATION_FOR_LOCAL_SEARCH);
              queryTxt.requestFocus();
              return;
          }
          executeSearch(queryTxt.getText(), locationTxt.getText(), SearchType.LOCAL);
      }      
    });
    
    Button searchEvent = (Button)findViewById(R.id.search_event);
    searchEvent.setOnClickListener(new OnClickListener(){
      @Override
      public void onClick(View v) {
          if(AppUtils.isBlank(queryTxt) && AppUtils.isBlank(locationTxt)){
              showMessage(PLEASE_ENTER_LOCATION_FOR_EVENT_SEARCH);
              queryTxt.requestFocus();
              return;
          } 
          executeSearch(null, locationTxt.getText(), SearchType.UPCOMING);
      }      
    });
    
    Button searchMovies = (Button)findViewById(R.id.topmovie);
    searchMovies.setOnClickListener(new OnClickListener(){

      @Override
      public void onClick(View v) {
        searchHelper.searchTopMovies();
      }
      
    });
    
    Button clearBttn = (Button)findViewById(R.id.clear);
    clearBttn.setOnClickListener(new OnClickListener(){
      @Override
      public void onClick(View v) {
        queryTxt.setText("");
        locationTxt.setText("");
      }      
    });
    
    Button newlist = (Button)findViewById(R.id.newlist);
    newlist.setOnClickListener(new OnClickListener(){
        @Override
        public void onClick(View v) {
            startActivityForResult(new Intent(Search.this, NewListBuilder.class), 1);
        }
        
    });
    
    Button savedlist = (Button)findViewById(R.id.savedlist);
    savedlist.setOnClickListener(new OnClickListener(){
      @Override
      public void onClick(View v) {
        Cursor lists = userData.fetchAllLists();
        if(lists.getCount() < 1){
          showMessage("Unable to find any saved lists, please create one first.");
          return;
        }
        showListDialog(lists, "Select a list");
      }
      
  });

  }
  private void executeSearch(CharSequence query, CharSequence location, SearchType type){
    searchHelper.startSearch(String.valueOf(query), String.valueOf(location), type);
  }
  
  public static final int ID_DIALOG_SEARCHING = 0;

  @Override
  protected Dialog onCreateDialog(int id) {
      if(id == ID_DIALOG_SEARCHING){
          ProgressDialog loadingDialog = new ProgressDialog(this);
          loadingDialog.setMessage("Searching...");
          loadingDialog.setIndeterminate(true);
          loadingDialog.setCancelable(true);
          return loadingDialog;
      }

      return super.onCreateDialog(id);
  }
  
  @Override
  protected void onSaveInstanceState(Bundle outState) {
      try {
          dismissDialog(ID_DIALOG_SEARCHING);
      } catch (Exception e) {
          //ignore error
          Log.e(Search.class.toString(), e.getMessage(), e);
      }
      super.onSaveInstanceState(outState);
  }
  
  @Override
  protected void onDestroy() {
    super.onDestroy();
    userData.close();
  }
  
  @Override
  public void onResume() {
      super.onResume();
      locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 500L /*.5 sec between update*/, 
              100.0f/*receive update if greater than 100m change*/ , onLocationChange);
      locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1000L /*1 sec between update*/, 
              500.0f/*receive update if greater than 100m change*/ , onLocationChange);
  }
  
  @Override
  public void onPause() {
      super.onPause();
      locationManager.removeUpdates(onLocationChange);
  }
  
  private void showMessage(String errorString) {
      Toast text = Toast.makeText(this, 
              errorString, Toast.LENGTH_SHORT);
      text.show();
  }
}